package effects;

import loadsave.Memento;
import loadsave.loadsaveobject.Iterator;
import loadsave.loadsaveobject.LoadSaveObject;
import loadsave.loadsaveobject.LoadSaveObjectComposite;
import stat.EntityStatList;
import stat.NonEntityStatList;
import stat.StatList;
import stat.StatType;
import visitors.EffectsVisitor;

/**
 * The DamageEffect class is meant to encapsulate
 * an effect that applies a negative delta in stats
 * from an entity. The class contains the appropriate
 * modifiers to compute the effect.  This class is
 * necessary as a target for double dispatch for the
 * Visitor class.
 * 
 * DamageEffect is in charge of computing the value
 * of damage from the source stats and provide that
 * to the client.
 * 
 * @author DangMH
 *
 */
public class DamageEffect extends Effect {
	private StatList damageStats;
	
	/**
	 * Empty constructor
	 */
	public DamageEffect() {
		damageStats = new NonEntityStatList();
		setMutator( -1 );
	}
	
	/**
	 * Parameterized Constructor
	 * @param modelName
	 * Name of the modal image
	 * @param statList
	 * Stats for damage influence
	 */
	public DamageEffect( String modelName, StatList statList ) {
		super( modelName );
		this.damageStats = statList;
		setMutator( -1 );
	}
	
	/**
	 * Visitor interface
	 */
	public void accept( EffectsVisitor ev ) {
		ev.visitDamageEffect( this );
	}

	/**
	 * Computes the delta stats, assumes addStats
	 */
	public StatList computeStats() {
		StatList ret = new NonEntityStatList();
		
		for( StatType st : getOutputStats() ) {
			ret.addStat( st, computeDamage() );
		}
		
		return ret;
	}
	
	/**
	 * private method to derive the delta stats
	 */
	private int computeDamage() {
		int ret = 0;
		
		for( StatType st : getRelevantStats() ) {
			ret += damageStats.getStat( st );
		}
		
		return ret;
	}

	/**
	 * public mutator for stats
	 */
	public void setStats(StatList statList) {
		damageStats = statList;
	}

	@Override
	public Memento getMemento() {
		return new Memento() {

			@Override
			public LoadSaveObject getState() {
				LoadSaveObject lso = DamageEffect.super.getMemento().getState();
				LoadSaveObjectComposite toReturn = new LoadSaveObjectComposite("", "DamageEffect");
				Iterator<LoadSaveObject> i = lso.getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					toReturn.add(i.getCurrKey().getValue(), i.getCurrVal());
				}
				lso = damageStats.getMemento().getState();
				lso.setName("damageStats");
				toReturn.add(lso.getName(), lso);
				return toReturn;
			}

			@Override
			public void restoreState(LoadSaveObject lso) {
				DamageEffect.super.getMemento().restoreState(lso);
				damageStats = new EntityStatList();
				damageStats.getMemento().restoreState(lso.get("damageStats"));
			}
			
		};
	}

	@Override
	public DamageEffect clone() {
		StatList dStats = new EntityStatList();
		dStats.addStats(damageStats);
		
		DamageEffect ret = new DamageEffect(getName(), dStats);
		
		for( StatType st : getRelevantStats() ) {
			ret.addRelevantStat( st );
		}
		
		for( StatType st : getOutputStats() ) {
			ret.addOutputStat( st );
		}
		
		return ret;
	}
}
